package com.arpa.oms.service.impl;

import cn.hutool.core.util.IdUtil;
import com.arpa.core.utils.collection.CollectionUtil;
import com.arpa.ntocc.common.common.cache.PartyCache;
import com.arpa.ntocc.common.common.cache.ShipmentCache;
import com.arpa.ntocc.common.common.exception.ServiceException;
import com.arpa.ntocc.common.common.util.CommonUtil;
import com.arpa.ntocc.common.common.util.UserUtil;
import com.arpa.oms.cache.UnpackRuleCache;
import com.arpa.oms.domain.dto.OmsUnpackRuleDTO;
import com.arpa.oms.domain.entity.OmsUnpackGoods;
import com.arpa.oms.domain.entity.OmsUnpackRule;
import com.arpa.oms.domain.enums.OmsUnpackRuleEnum;
import com.arpa.oms.domain.enums.OmsUnpackRuleTypeEnum;
import com.arpa.oms.domain.vo.OmsUnpackRuleVO;
import com.arpa.oms.mapper.OmsUnpackRuleMapper;
import com.arpa.oms.service.IOmsUnpackGoodsService;
import com.arpa.oms.service.IOmsUnpackRuleService;
import com.arpa.wms.cache.ShopCache;
import com.arpa.wms.domain.consts.PropertyConst;
import com.arpa.wms.domain.entity.Goods;
import com.arpa.wms.domain.enums.StatusEnum;
import com.arpa.wms.service.IGoodsService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 拆单规则 服务实现类
 * </p>
 *
 * @author spb
 * @since 2021-07-23
 */
@Service
public class OmsUnpackRuleServiceImpl extends ServiceImpl<OmsUnpackRuleMapper, OmsUnpackRule> implements IOmsUnpackRuleService {

    @Resource
    private PartyCache partyCache;
    @Resource
    private ShipmentCache shipmentCache;
    @Resource
    private ShopCache shopCache;

    @Autowired
    private IGoodsService iGoodsService;
    @Autowired
    private IOmsUnpackGoodsService iOmsUnpackGoodsService;
    @Autowired
    private UnpackRuleCache unpackRuleCache;

    @Override
    public Integer listCount(OmsUnpackRuleDTO unpackRuleDTO) {
        LambdaQueryWrapper<OmsUnpackRule> queryWrapper = getQueryWrapper(new QueryWrapper<OmsUnpackRule>(), unpackRuleDTO);
        Integer count = baseMapper.selectCount(queryWrapper);
        return count;
    }

    @Override
    public List<OmsUnpackRuleVO> listPage(OmsUnpackRuleDTO unpackRuleDTO) {
        List<OmsUnpackRuleVO> resultList = new ArrayList<>();
        //排序字段名需要驼峰转数据库下划线类型字段名
        if (StringUtils.isNotEmpty(unpackRuleDTO.getSortField())) {
            unpackRuleDTO.setSortField(CommonUtil.camel2Underline(unpackRuleDTO.getSortField()));
        }
        QueryWrapper<OmsUnpackRule> query = new QueryWrapper<OmsUnpackRule>();
        if (StringUtils.isNotBlank(unpackRuleDTO.getSortField())) {
            if (StringUtils.isNotBlank(unpackRuleDTO.getSortType()) && unpackRuleDTO.getSortType().toLowerCase().equals("asc")) {
                query.orderByAsc(unpackRuleDTO.getSortField());
            } else {
                query.orderByDesc(unpackRuleDTO.getSortField());
            }
        } else {
            query.orderByDesc("gmt_created");
        }
        LambdaQueryWrapper<OmsUnpackRule> queryWrapper = getQueryWrapper(query, unpackRuleDTO);
        int start = (unpackRuleDTO.getPageNum()-1)*unpackRuleDTO.getPageSize();
        queryWrapper.last("limit " + start + " , " + unpackRuleDTO.getPageSize());
        List<OmsUnpackRule> list = baseMapper.selectList(queryWrapper);
        if (CollectionUtil.isNotEmpty(list)) {
            resultList = list.stream().map(v -> {
                OmsUnpackRuleVO vo = new OmsUnpackRuleVO();
                BeanUtils.copyProperties(v, vo);
                vo.setStatusText(StatusEnum.getEnumByValue(vo.getStatus()).getDesc());
                return vo;
            }).collect(Collectors.toList());
        }
        return resultList;
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public boolean create(OmsUnpackRule entity) {
        entity.setCode(IdUtil.simpleUUID());
        entity.setCreatedBy(UserUtil.getCode());
        entity.setModifiedBy(UserUtil.getCode());
        String loginName = partyCache.translate(UserUtil.getCode());
        entity.setCreatedName(loginName);
        entity.setModifiedName(loginName);
        entity.setStatus(StatusEnum.UNACTIVE.getValue());
        entity.setShipmentName(shipmentCache.translate(entity.getShipmentCode()));
        entity.setShopName(shopCache.translate(entity.getShopCode()));
        int num = baseMapper.insert(entity);
        if (num <= 0) {
            return false;
        }
        if (OmsUnpackRuleTypeEnum.BY_GOODS.getValue().equals(entity.getRuleType())) {
            if (OmsUnpackRuleEnum.PART_GOODS.getValue().equals(entity.getAllGoods())) {
                List<String> unpackGoods = entity.getUnpackGoods();
                if (CollectionUtil.isEmpty(unpackGoods)) {
                    throw new ServiceException("按商品、按特定商品拆单时，商品不能为空");
                }
                List<Goods> goodsList = iGoodsService.list(new QueryWrapper<Goods>().lambda().in(Goods::getCode, unpackGoods));
                if (CollectionUtil.isEmpty(goodsList)) {
                    throw new ServiceException("查询对应商品不存在");
                }
                List<OmsUnpackGoods> list = goodsList.stream().map(v -> {
                    OmsUnpackGoods omsUnpackGoods = new OmsUnpackGoods();
                    BeanUtils.copyProperties(v, omsUnpackGoods);
                    omsUnpackGoods.setGoodsCode(v.getCode());
                    omsUnpackGoods.setUnpackRuleCode(entity.getCode());
                    omsUnpackGoods.setCode(IdUtil.simpleUUID());
                    omsUnpackGoods.setCreatedBy(UserUtil.getCode());
                    omsUnpackGoods.setModifiedBy(UserUtil.getCode());
                    omsUnpackGoods.setCreatedName(loginName);
                    omsUnpackGoods.setModifiedName(loginName);
                    return omsUnpackGoods;
                }).collect(Collectors.toList());
                iOmsUnpackGoodsService.saveBatch(list);
            }
        } else if (OmsUnpackRuleTypeEnum.BY_WEIGHT.getValue().equals(entity.getRuleType())) {

        } else if (OmsUnpackRuleTypeEnum.BY_VOLUME.getValue().equals(entity.getRuleType())) {

        } else if (OmsUnpackRuleTypeEnum.BY_QUANTITY.getValue().equals(entity.getRuleType())) {
            if (OmsUnpackRuleEnum.PART_GOODS.getValue().equals(entity.getAllGoods())) {
                List<String> unpackGoods = entity.getUnpackGoods();
                if (CollectionUtil.isEmpty(unpackGoods)) {
                    throw new ServiceException("按数量、按特定商品拆单时，商品不能为空");
                }
                List<Goods> goodsList = iGoodsService.list(new QueryWrapper<Goods>().lambda().in(Goods::getCode, unpackGoods));
                if (CollectionUtil.isEmpty(goodsList)) {
                    throw new ServiceException("查询对应商品不存在");
                }
                List<OmsUnpackGoods> list = goodsList.stream().map(v -> {
                    OmsUnpackGoods omsUnpackGoods = new OmsUnpackGoods();
                    BeanUtils.copyProperties(v, omsUnpackGoods);
                    omsUnpackGoods.setGoodsCode(v.getCode());
                    omsUnpackGoods.setUnpackRuleCode(entity.getCode());
                    omsUnpackGoods.setCode(IdUtil.simpleUUID());
                    omsUnpackGoods.setCreatedBy(UserUtil.getCode());
                    omsUnpackGoods.setModifiedBy(UserUtil.getCode());
                    omsUnpackGoods.setCreatedName(loginName);
                    omsUnpackGoods.setModifiedName(loginName);
                    return omsUnpackGoods;
                }).collect(Collectors.toList());
                iOmsUnpackGoodsService.saveBatch(list);
            }
        } else {
            throw new ServiceException("拆单规则类型无法识别");
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public Boolean updateByCode(OmsUnpackRule entity) {
        entity.setModifiedBy(UserUtil.getCode());
        String loginName = partyCache.translate(UserUtil.getCode());
        entity.setModifiedName(loginName);
        entity.setStatus(StatusEnum.UNACTIVE.getValue());
        entity.setShipmentName(shipmentCache.translate(entity.getShipmentCode()));
        entity.setShopName(shopCache.translate(entity.getShopCode()));
        Integer num = baseMapper.update(entity, new QueryWrapper<OmsUnpackRule>().lambda().eq(OmsUnpackRule::getCode, entity.getCode()));
        if (num > 0) {
            iOmsUnpackGoodsService.remove(new QueryWrapper<OmsUnpackGoods>().lambda().eq(OmsUnpackGoods::getUnpackRuleCode, entity.getCode()));
            if (OmsUnpackRuleTypeEnum.BY_GOODS.getValue().equals(entity.getRuleType())) {
                if (OmsUnpackRuleEnum.PART_GOODS.getValue().equals(entity.getAllGoods())) {
                    List<String> unpackGoods = entity.getUnpackGoods();
                    if (CollectionUtil.isEmpty(unpackGoods)) {
                        throw new ServiceException("按商品、按特定商品拆单时，商品不能为空");
                    }
                    List<Goods> goodsList = iGoodsService.list(new QueryWrapper<Goods>().lambda().in(Goods::getCode, unpackGoods));
                    if (CollectionUtil.isEmpty(goodsList)) {
                        throw new ServiceException("查询对应商品不存在");
                    }
                    List<OmsUnpackGoods> list = goodsList.stream().map(v -> {
                        OmsUnpackGoods omsUnpackGoods = new OmsUnpackGoods();
                        BeanUtils.copyProperties(v, omsUnpackGoods);
                        omsUnpackGoods.setGoodsCode(v.getCode());
                        omsUnpackGoods.setUnpackRuleCode(entity.getCode());
                        omsUnpackGoods.setCode(IdUtil.simpleUUID());
                        omsUnpackGoods.setCreatedBy(UserUtil.getCode());
                        omsUnpackGoods.setModifiedBy(UserUtil.getCode());
                        omsUnpackGoods.setCreatedName(loginName);
                        omsUnpackGoods.setModifiedName(loginName);
                        return omsUnpackGoods;
                    }).collect(Collectors.toList());
                    iOmsUnpackGoodsService.saveBatch(list);
                }
            } else if (OmsUnpackRuleTypeEnum.BY_WEIGHT.getValue().equals(entity.getRuleType())) {

            } else if (OmsUnpackRuleTypeEnum.BY_VOLUME.getValue().equals(entity.getRuleType())) {

            } else if (OmsUnpackRuleTypeEnum.BY_QUANTITY.getValue().equals(entity.getRuleType())) {
                if (OmsUnpackRuleEnum.PART_GOODS.getValue().equals(entity.getAllGoods())) {
                    List<String> unpackGoods = entity.getUnpackGoods();
                    if (CollectionUtil.isEmpty(unpackGoods)) {
                        throw new ServiceException("按数量、按特定商品拆单时，商品不能为空");
                    }
                    List<Goods> goodsList = iGoodsService.list(new QueryWrapper<Goods>().lambda().in(Goods::getCode, unpackGoods));
                    if (CollectionUtil.isEmpty(goodsList)) {
                        throw new ServiceException("查询对应商品不存在");
                    }
                    List<OmsUnpackGoods> list = goodsList.stream().map(v -> {
                        OmsUnpackGoods omsUnpackGoods = new OmsUnpackGoods();
                        BeanUtils.copyProperties(v, omsUnpackGoods);
                        omsUnpackGoods.setGoodsCode(v.getCode());
                        omsUnpackGoods.setUnpackRuleCode(entity.getCode());
                        omsUnpackGoods.setCode(IdUtil.simpleUUID());
                        omsUnpackGoods.setCreatedBy(UserUtil.getCode());
                        omsUnpackGoods.setModifiedBy(UserUtil.getCode());
                        omsUnpackGoods.setCreatedName(loginName);
                        omsUnpackGoods.setModifiedName(loginName);
                        return omsUnpackGoods;
                    }).collect(Collectors.toList());
                    iOmsUnpackGoodsService.saveBatch(list);
                }
            } else {
                throw new ServiceException("拆单规则类型无法识别");
            }
            unpackRuleCache.flushACacheByShipmentCode(UserUtil.getLoginWarehouseCodeOrShipmentCode());
            return true;
        }
        return false;
    }

    @Override
    public boolean active(String code, String value) {
        List<OmsUnpackRule> list = baseMapper.selectList(new QueryWrapper<OmsUnpackRule>().lambda().eq(OmsUnpackRule::getCode, code));
        if (CollectionUtil.isNotEmpty(list)) {
            list.forEach(v -> {
                List<OmsUnpackRule> hasList = baseMapper.selectList(new QueryWrapper<OmsUnpackRule>().lambda().eq(OmsUnpackRule::getShopCode, v.getShopCode()).eq(OmsUnpackRule::getRuleType, v.getRuleType()).ne(OmsUnpackRule::getCode, code).eq(OmsUnpackRule::getStatus, StatusEnum.ACTIVE.getValue()));
                if (OmsUnpackRuleEnum.ALL_GOODS.getValue().equals(v.getAllGoods())) {
                    if (CollectionUtil.isNotEmpty(hasList)) {
                        throw new ServiceException("已有相同规则[" + hasList.get(0).getRuleName() + "]启用中, 启用失败");
                    }
                } else {
                    if (CollectionUtil.isNotEmpty(hasList)) {
                        List<OmsUnpackGoods> goodsList = iOmsUnpackGoodsService.list(new QueryWrapper<OmsUnpackGoods>().lambda().eq(OmsUnpackGoods::getUnpackRuleCode, v.getCode()));
                        List<String> goodCodeList = goodsList.stream().map(g -> g.getGoodsCode()).collect(Collectors.toList());

                        hasList.forEach(h -> {
                            if (OmsUnpackRuleEnum.ALL_GOODS.getValue().equals(h.getAllGoods())) {
                                throw new ServiceException("规则：[" + h.getRuleName() + "] 已启用并包含所有商品");
                            }
                            List<OmsUnpackGoods> goodsListRunning = iOmsUnpackGoodsService.list(new QueryWrapper<OmsUnpackGoods>().lambda().eq(OmsUnpackGoods::getUnpackRuleCode, h.getCode()));
                            List<String> goodCodeListRunning = goodsListRunning.stream().map(g -> g.getGoodsCode()).collect(Collectors.toList());
                            boolean flag = goodCodeList.retainAll(goodCodeListRunning);
                            if (flag) {
                                Map<String, OmsUnpackGoods> maps = goodsList.stream().collect(Collectors.toMap(e -> e.getGoodsCode(), e -> e));
                                StringBuffer tip = new StringBuffer();
                                goodCodeList.forEach(s -> {
                                    tip.append(maps.get(s).getName());
                                });
                                throw new ServiceException("商品：[" + tip + "] 已经在规则：[" + h.getRuleName() + "] 中使用中");
                            }
                        });
                    }
                }
                v.setStatus(value);
            });
            unpackRuleCache.flushACacheByShipmentCode(UserUtil.getLoginWarehouseCodeOrShipmentCode());
            return updateBatchById(list);
        }
        return false;
    }

    @Override
    public boolean unactive(String code, String value) {
        List<OmsUnpackRule> list = baseMapper.selectList(new QueryWrapper<OmsUnpackRule>().lambda().eq(OmsUnpackRule::getCode, code));
        if (CollectionUtil.isNotEmpty(list)) {
            list.forEach(v -> v.setStatus(value));
            unpackRuleCache.flushACacheByShipmentCode(UserUtil.getLoginWarehouseCodeOrShipmentCode());
            return updateBatchById(list);
        }
        return false;
    }

    @Override
    public Map<String, Integer> deleteByCodes(List<String> codes) {
        int num = baseMapper.delete(new QueryWrapper<OmsUnpackRule>().lambda().in(OmsUnpackRule::getCode, codes));
        if (num > 0) {
            iOmsUnpackGoodsService.remove(new QueryWrapper<OmsUnpackGoods>().lambda().in(OmsUnpackGoods::getUnpackRuleCode, codes));
        }
        Map<String, Integer> resultData = new HashMap<>();
        resultData.put(PropertyConst.SUCCESS, num);
        unpackRuleCache.flushACacheByShipmentCode(UserUtil.getLoginWarehouseCodeOrShipmentCode());
        return resultData;
    }

    @Override
    public OmsUnpackRule getDetailInfoByCode(String code) {
        OmsUnpackRule omsUnpackRule = baseMapper.selectOne(new QueryWrapper<OmsUnpackRule>().lambda().eq(OmsUnpackRule::getCode, code));
        if (omsUnpackRule != null) {
            List<OmsUnpackGoods> goodsList = iOmsUnpackGoodsService.list(new QueryWrapper<OmsUnpackGoods>().lambda().eq(OmsUnpackGoods::getUnpackRuleCode, omsUnpackRule.getCode()).orderByAsc(OmsUnpackGoods::getName));
            omsUnpackRule.setUnpackGoods(goodsList.stream().map(v -> v.getGoodsCode()).collect(Collectors.toList()));
            omsUnpackRule.setGoodNameList(goodsList.stream().map(v -> v.getName()).collect(Collectors.toList()));
        }
        return omsUnpackRule;
    }


    private LambdaQueryWrapper<OmsUnpackRule> getQueryWrapper(QueryWrapper query, OmsUnpackRuleDTO unpackRuleDTO) {
        LambdaQueryWrapper<OmsUnpackRule> queryWrapper = query.lambda();
        if (StringUtils.isNotBlank(unpackRuleDTO.getStatus())) {
            queryWrapper.eq(OmsUnpackRule::getStatus, unpackRuleDTO.getStatus());
        }
        if (StringUtils.isNotBlank(unpackRuleDTO.getShipmentCode())) {
            queryWrapper.eq(OmsUnpackRule::getShipmentCode, unpackRuleDTO.getShipmentCode());
        } else {
            queryWrapper.eq(OmsUnpackRule::getShipmentCode, UserUtil.getLoginWarehouseCodeOrShipmentCode());
        }
        if (StringUtils.isNotBlank(unpackRuleDTO.getModifiedBy())) {
            queryWrapper.eq(OmsUnpackRule::getModifiedBy, unpackRuleDTO.getModifiedBy());
        }
        if (StringUtils.isNotBlank(unpackRuleDTO.getCreatedBy())) {
            queryWrapper.eq(OmsUnpackRule::getCreatedBy, unpackRuleDTO.getCreatedBy());
        }
        if (StringUtils.isNotBlank(unpackRuleDTO.getShopCode())) {
            queryWrapper.eq(OmsUnpackRule::getShopCode, unpackRuleDTO.getShopCode());
        }
        if (StringUtils.isNotBlank(unpackRuleDTO.getRuleType())) {
            queryWrapper.eq(OmsUnpackRule::getRuleType, unpackRuleDTO.getRuleType());
        }
        if ((null != unpackRuleDTO.getGmtCreatedStart()) && (null != unpackRuleDTO.getGmtCreatedEnd())) {
            queryWrapper.between(OmsUnpackRule::getGmtCreated, unpackRuleDTO.getGmtCreatedStart(), unpackRuleDTO.getGmtCreatedEnd());
        } else {
            if (null != unpackRuleDTO.getGmtCreatedStart()) {
                queryWrapper.ge(OmsUnpackRule::getGmtCreated, unpackRuleDTO.getGmtCreatedStart());
            }
            if (null != unpackRuleDTO.getGmtCreatedEnd()) {
                queryWrapper.le(OmsUnpackRule::getGmtCreated, unpackRuleDTO.getGmtCreatedEnd());
            }
        }

        if ((null != unpackRuleDTO.getGmtModifiedStart()) && (null != unpackRuleDTO.getGmtModifiedEnd())) {
            queryWrapper.between(OmsUnpackRule::getGmtModified, unpackRuleDTO.getGmtModifiedStart(), unpackRuleDTO.getGmtModifiedEnd());
        } else {
            if (null != unpackRuleDTO.getGmtModifiedStart()) {
                queryWrapper.ge(OmsUnpackRule::getGmtModified, unpackRuleDTO.getGmtModifiedStart());
            }
            if (null != unpackRuleDTO.getGmtModifiedEnd()) {
                queryWrapper.le(OmsUnpackRule::getGmtModified, unpackRuleDTO.getGmtModifiedEnd());
            }
        }
        if (StringUtils.isNotBlank(unpackRuleDTO.getRuleName())) {
            queryWrapper.like(OmsUnpackRule::getRuleName, unpackRuleDTO.getRuleName());
        }
        if (StringUtils.isNotBlank(unpackRuleDTO.getRemark())) {
            queryWrapper.like(OmsUnpackRule::getRemark, unpackRuleDTO.getRemark());
        }
        if (StringUtils.isNotBlank(unpackRuleDTO.getModifiedName())) {
            queryWrapper.like(OmsUnpackRule::getModifiedName, unpackRuleDTO.getModifiedName());
        }
        if (StringUtils.isNotBlank(unpackRuleDTO.getCreatedName())) {
            queryWrapper.like(OmsUnpackRule::getCreatedName, unpackRuleDTO.getCreatedName());
        }
        return queryWrapper;
    }
}
